package com.lenovo.leos.letools.lenovodata;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.lenovo.leos.letools.db.FileDownloadEntity;
import com.lenovo.leos.letools.db.FileDownloadService;
import com.lenovo.leos.letools.domain.Folder;
import com.lenovo.leos.letools.domain.LoadFile;
import com.lenovo.leos.letools.exception.BadFileException;
import com.lenovo.leos.letools.exception.NetException;
import com.lenovo.leos.letools.interaces.DownloadProgressListener;
import com.lenovo.leos.letools.utils.Constants;
import com.lenovo.leos.letools.utils.JSONParser;
import com.lenovo.leos.letools.utils.ListFileUseParams;

public class DownLoadServer {

	private FileDownloadService fileService;
	private Context context;
	private BaseNetClientServer baseClient;
	private static DownLoadServer instance;
	
	/**
	 * 下载任务容器 key为要下载文件的Id； value为对应这个文件的下载线程DownLoadThread
	 * 表示开启的要下载操作的线程集合
	 */
	private Map<String, DownLoadThread> fileTaskContainer;
	/**
	 * 下载任务容器 key为要下载文件夹的Id； value为对应这个文件夹下的所有要下载文件的线程DownLoadThread
	 * 表示开启的要下载操作的线程集合
	 */
	private Map<String, List<DownLoadThread>> dirTaskContainer;

	private DownLoadServer(Context context) {
		this.context = context;
		fileService = new FileDownloadService(context);// 打开数据库
		fileTaskContainer = new HashMap<String, DownLoadThread>();
		dirTaskContainer = new HashMap<String,List<DownLoadThread>>();
		baseClient = new BaseNetClientServer();
	}

	public static DownLoadServer getInstance(Context context){
		if(null == instance){
			instance = new DownLoadServer(context);
		}
		return instance;
	}
	/**
	 * 创建一个下载文件的任务
	 * @param fileid
	 * @param targetFilePath
	 * @param fileNewName
	 * @throws NetException
	 */
	public void createFileLoadTask(String fileid,String targetFilePath,String fileNewName) throws NetException {
		FileDownloadEntity enty = fileService.getFileDownloadEntity(fileid);
		if(enty!=null){
			switch (enty.getLoadover()) {
			case FileDownloadService.loadover_yes:
				throw new RuntimeException("您要下载的文件已经下载完毕！" + fileid);
			case FileDownloadService.loadover_no:
				throw new RuntimeException("当前已经存在对应文件id的下载任务" + fileid);
			default:
				break;
			}
		}
		List<String> retVal = baseClient.predownload(context, fileid);
		if(retVal == null) return;
		String fileOldName = "";//文件原始名称
		String fileLen = "0";//文件长度
		//取得文件长度和原始名称
		for (String cookieVal : retVal) {
			if (cookieVal.contains("FILELENGTH")) {
				fileLen = cookieVal.substring(cookieVal.indexOf("=") + 1);
			}
			if (cookieVal.contains("FILENAME")) {
				fileOldName = cookieVal.substring(cookieVal.indexOf("=") + 1);
			}
		}
		
		File file = new File(targetFilePath, fileOldName);
		if(fileNewName!=null){
			file = new File(targetFilePath, fileNewName);
		}
		String wholeFilePath = file.getPath();//文件的全路径
		fileService.save(fileid,Integer.parseInt(fileLen),wholeFilePath,null,null);//将这个任务存入数据库
	}
	
	/**
	 * 创建一个下载文件夹任务
	 * 
	 * @param fileid
	 */
	public void createDirLoadTask(String dirid,String dirname,String targetFilePath)  throws NetException {
		List<FileDownloadEntity> fuds = fileService.getEntityByTopDirid(dirid);
		if(fuds.size()!=0){
			int loadover = FileDownloadService.loadover_yes;
			for(FileDownloadEntity fud:fuds){
				if(fud.getLoadover()==FileDownloadService.loadover_no){
					loadover=FileDownloadService.loadover_no;
				}
			}
			switch (loadover) {
				case FileDownloadService.loadover_yes:
					throw new RuntimeException("您要下载的文件已经下载完毕！" + dirname);
				case FileDownloadService.loadover_no:
					throw new RuntimeException("当前已经存在对应文件id的下载任务" + dirname);
				default:
					break;
			}
		}
		String topDiridWholePath = targetFilePath+"/"+dirname;
		List<Folder> rootDir = new ArrayList<Folder>();
		rootDir.add(new Folder(dirid,dirname));
		Map<String,List<LoadFile>> dirFileMap = new HashMap<String, List<LoadFile>>();
		this.recursiveMapingWholePathAndFileInf(context,rootDir,new File(targetFilePath), dirFileMap);
		
		Set<Map.Entry<String,List<LoadFile>>> entitys = dirFileMap.entrySet();
		for(Map.Entry<String,List<LoadFile>> entry:entitys){
			String wholePath = entry.getKey();
			List<LoadFile> loadFiles = entry.getValue();
			for(LoadFile lf:loadFiles){
				String fileWholePath = wholePath+"/"+lf.getFilename();
				String fileid = lf.getId();
				int filelen = Integer.parseInt(lf.getFileLen());
				//将这个任务存入数据库,也就是将这个文件下的所有子文件放入数据库
				fileService.save(fileid,filelen,fileWholePath,dirid,topDiridWholePath);
			}
		}
	}
	
	/**
	 * 递归下载并在sdcard根目录下创建文件夹，
	 * 并将保存到本地的文件夹路径与它所对应的所有子文件放入一个map中
	 * 目的是下载文件的时候，从map中取出文件id并下载对应的dir中
	 * @param context
	 * @param folders
	 * @param targetDir
	 * @param dirFileMap
	 * @throws Exception 
	 * @throws Exception
	 */
	private void recursiveMapingWholePathAndFileInf(Context context,
			List<Folder> folders, File targetDir,Map<String,List<LoadFile>> dirFileMap) throws NetException {
		for (Folder folder : folders) {
			Log.i("dirId", "======dir wholePath=====" + targetDir.getPath());
			File dir = new File(targetDir, folder.getName());
			dir.mkdir();
			
			ListFileUseParams lfp = new ListFileUseParams();
			lfp.dirid = folder.getId();
			String fileInfObj = "";
			List<LoadFile> loadFiles=null;
			
			fileInfObj = baseClient.listFile(context, lfp);// 得到指定文件夹下的所有子文件
			try {
				loadFiles = JSONParser.parseListFile(fileInfObj);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			if(loadFiles!=null){
				dirFileMap.put(dir.getPath(),loadFiles);
			}

			String dirInfObj = "";
			List<Folder> dirIdInfs = null;
			
			dirInfObj = baseClient.listDir(context, folder.getId());
			try {
				dirIdInfs = JSONParser.parseListdirs(dirInfObj);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			if (dirIdInfs == null) {
				return;
			} else {
				recursiveMapingWholePathAndFileInf(context, dirIdInfs, dir,dirFileMap);
			}
		}
	}
	/**
	 * 开启一个下载单个文件的线程
	 * *@param fileid
	 * @param pb
	 */
	public void startDownLoadThreadByFile(String fileid, final ProgressBar pb,final TextView tv,int fileLen) {
		FileDownloadEntity entity = fileService.getFileDownloadEntity(fileid);
		if(entity!=null){
			//此文件已经被下载完成
			if(entity.getLoadover()==FileDownloadService.loadover_yes){
				Toast.makeText(context,"this file has been download over!",Toast.LENGTH_SHORT).show();
				return;
			}
		}
		if(fileTaskContainer.get(fileid)!=null && fileTaskContainer.get(fileid).isAlive()){
			Toast.makeText(context,"this file is downloading!",Toast.LENGTH_SHORT).show();
			return;
		}
		DownLoadThread ds = new DownLoadThread(context, fileid,fileLen);
		fileTaskContainer.put(fileid, ds);// 启动一个线程，就将这个线程放入任务容器
		ds.setDownloadProgressListener(new DownloadProgressListener() {
			public void onDownloadSize(int size) {
				//modify by gaoge ,here change the progressBar size is operate by handler,not listener
//				pb.setProgress(size);// 更新进度条
			}
			
			public void onChangeDownText(String value){
//				runOnUi(tv,value);
			}
			
			public void onDownloadOver(String fileid) {
				//fileid文件下载完毕
				Log.i("afff","================this file has been download over!===============");
			}
			public void onDownloadException(int errorStyle) {
				//下载过程中产生errorStyle异常
				Log.i("afff","===============net exception!================" + errorStyle);
				runOnUi(context);
			}
			public void onDownloadPause(String fileid) {
				//filed下载暂停
				Log.i("afff","================this file has been download pause!===============");
			}
		});
		ds.setTv_percent(tv);
		ds.setmProgressBar(pb);
		ds.start();
	}
	
	private void runOnUi(final Context context){
		mHandler.post(new Runnable() {
			@Override
			public void run() {
//				Toast.makeText(context, "目标文件或文件夹已被删除或损坏！", Toast.LENGTH_SHORT).show();
			}
		});
	}
	
	/**
	 * 统计同一顶层文件夹下的所有子文件已经下载了多长的数据 
	 * @author Administrator
	 *
	 */
	public  TotalFilelenPreDir getNewTotalFilelenPreDir(int mulFileTotalLen,ProgressBar progressBar,TextView tv){
		return new TotalFilelenPreDir(mulFileTotalLen,progressBar,tv);
	}
	
	 public class TotalFilelenPreDir{
		public int mulFileTotalLen=0;
		public DownloadProgressListener downloadProgressListener;
		private ProgressBar dir_mProgressBar;
		private TextView dir_percent;
		
		public TotalFilelenPreDir(int mulFileTotalLen,ProgressBar progressBar,TextView tv){
			this.mulFileTotalLen = mulFileTotalLen;
			this.dir_mProgressBar = progressBar;
			this.dir_percent = tv;
		}
		public TotalFilelenPreDir(){
			
		}
		
		public void setDirProgressBar(ProgressBar progressBar){
			this.dir_mProgressBar = progressBar;
		}
		
		public void setDirPercent(TextView tv){
			this.dir_percent = tv;
		}
		
		public ProgressBar getDirProgressBar(){
			return dir_mProgressBar;
		}
		
		public TextView getDirPercent(){
			return dir_percent;
		}
		
		public void setDownloadProgressListener(
				DownloadProgressListener downloadProgressListener) {
			this.downloadProgressListener = downloadProgressListener;
		}
	}
	/**
	 * 开启一个下载文件夹的多个线程（每个文件对应一个）
	 */
	public void startDownLoadThreadByDir(String dirid, final ProgressBar pb,final TextView tv,int dirLen) {
		Log.i("mulFileTotalLen","=========================startDownLoadThreadByDir==============");
		List<FileDownloadEntity> entitys = fileService.getEntityByTopDirid(dirid);
		int totallen = 0;
		for(FileDownloadEntity entity:entitys){
			totallen+=entity.getFilelen();
		}
		final int countlen=totallen;
		List<DownLoadThread> dts = new ArrayList<DownLoadThread>();
		
		TotalFilelenPreDir mulFileTotalLen = new TotalFilelenPreDir();
		//add by gaoge 2011-04-26
		mulFileTotalLen.setDirPercent(tv);
		mulFileTotalLen.setDirProgressBar(pb);
		mulFileTotalLen.setDownloadProgressListener(new DownloadProgressListener() {
			public void onDownloadSize(int size) {
//				Log.i("mulFileTotalLen","======mulFileTotalLen======="+size+"====="+countlen);
//				pb.setProgress(size);
			}
			public void onDownloadPause(String fileid){}
			public void onDownloadOver(String fileid){}
			public void onDownloadException(int errorStyle){}
			@Override
			public void onChangeDownText(String value) {
//				runOnUi(tv,value);
			}
		});
		for(FileDownloadEntity entity:entitys){
			Log.i("entity.getDownlength()","======================================="+entity.getDownlength());
			if(entity.getDownlength()!=entity.getFilelen()){//当前文件没有下载完成时
				DownLoadThread dt = new DownLoadThread(context,entity.getDownpath(),mulFileTotalLen,dirLen);//开启文件下的一个文件下载任务
				dts.add(dt);
				dt.start();
			}
		}
		dirTaskContainer.put(dirid,dts);
	}
	/**
	 * 暂止一个文件下载线程
	 * 
	 * @param fileid
	 */
	public void pauseDownLoadFileThread(String fileid) {
		DownLoadThread pauseDs = getDownloadThread(fileid);
		if(pauseDs!=null){
			pauseDs.set_flag_pause(true);// 暂停当前下载任务
			fileTaskContainer.remove(fileid);// 从任务线程容器中清除这个线程
		}
	}
	/**
	 * 暂止一个文件夹下载线程
	 * 
	 * @param fileid
	 */
	public void pauseDownLoadDirThread(String dirid) {
		List<DownLoadThread> dts = dirTaskContainer.get(dirid);
		if(dts!=null){
			for(DownLoadThread dt : dts){
				if(dt.isAlive()) dt.set_flag_pause(true);
			}
			dirTaskContainer.remove(dirid);
		}
	}
	/**
	 * 删除一个文件下载任务
	 */
	public void destroyFileDownLoadThread(String fileid) {
		DownLoadThread dt = fileTaskContainer.get(fileid);
		if(dt!=null && dt.isAlive()){//当前线程正在执行
			pauseDownLoadFileThread(fileid);//暂停当前线程
		}
		fileService.deleteFile(fileid);
	}
	/**
	 * 删除一个文件文件夹下载任务
	 */
	public void destroyDirDownLoadThread(String topDirId) {
		pauseDownLoadDirThread(topDirId);//暂停所有线程
		fileService.deleteTopDir(topDirId);
	}

	/**
	 * 获得fileId对应的DownLoadThread对象
	 * 
	 * @param key
	 * @return
	 */
	public DownLoadThread getDownloadThread(String key) {
		DownLoadThread ds = fileTaskContainer.get(key);
		return ds;
	}
	
	/**
	 * 获得dirId对应的DownLoadThread对象
	 * 
	 * @param key
	 * @return
	 */
	public List<DownLoadThread> getDownloadDirThreads(String dirkey) {
		List<DownLoadThread> ds_list = dirTaskContainer.get(dirkey);
		return ds_list;
	}
	
	
	/**
	 * 取出文件所有的下载任务
	 * 
	 * @return
	 */
	public List<FileDownloadEntity> getFileLoadTask() {
		return fileService.getFile();
	}
	/**
	 * 取出文件夹所有的下载任务
	 * 
	 * @return
	 */
	public Map<String,List<FileDownloadEntity>> getDirLoadTask() {
		return fileService.getAllFileGroupByDir();
	}
	
	private void runOnUi(final TextView tv,final String value){
		for(int i=0;i<3;i++){
			Log.d("hahaha","runOnUi");
		}
		mHandler.post(new Runnable() {
			@Override
			public void run() {
				tv.setText(value);
			}
		});
	}
	
	private Handler mHandler = new Handler();
	public FileDownloadEntity getFileLoadTask(String path){
		return fileService.getFileDownloadEntity(path);
	}
	
	/**
	 * 取出单个文件
	 * 
	 * @return
	 */
	public FileDownloadEntity getFileDownloadEntity(String path){
		return fileService.getFileDownloadEntity(path);
	}
	
	/**
	 * 取出文件夹所有的下载任务
	 * 
	 * @return
	 */
	public Map<String,List<FileDownloadEntity>> getDirsLoadTask() {
		return fileService.getAllFileGroupByDir();
	}
	/**
	 * 取出指定topDirid的文件夹下载任务
	 * @param path
	 * @return
	 */
	public List<FileDownloadEntity> getDirLoadTask(String topDirid){
		return fileService.getEntityByTopDirid(topDirid);
	}
	
	//add by gaoge 2011-04-12
	public boolean isDownLoadOver(String strwholepath){
		boolean isLoadOver = false;
		try {
			File file = new File(strwholepath);
			if(file.isFile()){
//				for(int i=0;i<5;i++){
//					Log.d("downserver","################### strwholepath:" + strwholepath + ",is File");
//				}
				FileDownloadEntity entity = fileService.getFileDownloadEntityByRealPath(strwholepath);
				Log.d("DownLoadServer", "the strwholepath is =============" + strwholepath);
				Log.d("DownLoadServer", "the entity is =============" + entity);
				if(null != entity){
					isLoadOver = (1 == entity.getLoadover());
				}else{
					//数据库里没有该文件的记录，则默认是已经下载完的（前台程序好处理）
					return true;
				}
			}
			else if(file.isDirectory()){
//				for(int i=0;i<5;i++){
//					Log.d("downserver","################### strwholepath:" + strwholepath + ",is Dir");
//				}
				List<FileDownloadEntity> entities = fileService.getEntityByTopDirRealPath(strwholepath);
				if(null == entities){
					return true;
				}else{
					for(int i=0;i<entities.size();i++){
						FileDownloadEntity entity  = entities.get(i);
						if(0 == entity.getLoadover()){
							isLoadOver = false;
							break;
						}else{
							isLoadOver = true;
						}
					}
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
//		for(int i=0;i<5;i++){
//			Log.d("downserver","################### strwholepath:" + strwholepath + ",isLoadOver ? " + isLoadOver);
//		}
		return isLoadOver;
	}
	
	/**
	 * 取出文件所有的下载任务
	 * 
	 * @return
	 */
	public List<FileDownloadEntity> getFilesLoadTask() {
		return fileService.getFile();
	}
	
	/**
	 * 删除所有下载任务
	 */
	public void destoryAllTask(List<FileDownloadEntity> fileTasks,Map<String,List<FileDownloadEntity>> dirTasks){
		
		for(FileDownloadEntity fde:fileTasks){
			DownLoadThread pauseDs = getDownloadThread(fde.getDownpath());
			if(pauseDs!=null && pauseDs.isAlive()) pauseDs.set_flag_pause(true);// 暂停这个线程
		}
		Set<Map.Entry<String,List<FileDownloadEntity>>> dirTaskSet = dirTasks.entrySet();
		for(Map.Entry<String,List<FileDownloadEntity>> enty:dirTaskSet){
			List<DownLoadThread> dts = dirTaskContainer.get(enty.getKey());
			if(dts!=null){
				for(DownLoadThread ut : dts){
					if(ut!=null && ut.isAlive()) ut.set_flag_pause(true);// 暂停这个线程
				}
			}
		}
		fileService.deleteAll();
	}
	
	//add by gaoge 2011-04-27
	public String getParentRootPath(String filepath){
		return fileService.getParentRootPath(filepath);
	}
}
